import random

import requests
from django import forms
from apps.web.forms.bootstrap import BootStrapForm
from django.core.validators import RegexValidator
from apps.web import models
from django.core.exceptions import ValidationError
from utils import sendemail
from django_redis import get_redis_connection
from utils.encrypt import md5


class RegisterModelForm(BootStrapForm, forms.ModelForm):
    """用户注册表单"""
    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': '密码长度不能小于8位',
            'max_length': '密码长度不能大于64位'
        },
        widget=forms.PasswordInput
    )
    confirm_password = forms.CharField(
        label='确认密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': '密码长度不能小于8位',
            'max_length': '密码长度不能大于64位'
        },
        widget=forms.PasswordInput
    )
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label='验证码', widget=forms.TextInput)

    class Meta:
        model = models.UserInfo  # 指定模型类
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']

    def clean_username(self):
        username = self.cleaned_data.get('username')
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已经存在')
        return username

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已经存在')
        return email

    def clean_password(self):
        password = self.cleaned_data.get('password')
        md5_password = md5(password)  # 加密
        return md5_password

    def clean_confirm_password(self):
        confirm_password = self.cleaned_data.get('confirm_password')
        password = self.cleaned_data.get('password')
        if password != md5(confirm_password):
            raise ValidationError('两次输入密码不一致，请重新输入')
        return confirm_password

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已经被注册')
        return mobile_phone

    def clean_code(self):
        info_code = self.cleaned_data.get('code')
        email = self.cleaned_data.get('email')
        if not email:
            return info_code
        # 拿到redis里面的code
        conn = get_redis_connection()
        redis_code = conn.get(email)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')
        redis_str_code = redis_code.decode('utf-8')
        if str(info_code).strip() != redis_str_code:
            raise ValidationError('验证码不正确')
        return info_code


class SendSmsForm(forms.Form):
    email = forms.CharField(label='邮箱', validators=[
        RegexValidator(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', '邮箱格式错误'),
    ])

    def clean_email(self):
        """邮箱校验的钩子方法，校验是否未注册过"""
        # 拿到邮箱
        email = self.cleaned_data.get('email')
        # 去数据库中查找当前邮箱是否存在
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('该邮箱邮件存在')
        # 发邮件
        # 先生成随机验证码
        code = random.randrange(1000, 9999)
        # 调用文件发送
        sendemail.send_to_one(email, code)
        # 验证码写入redis
        conn = get_redis_connection()
        conn.set(email, code, ex=60)
        return email


class LoginForm(BootStrapForm, forms.Form):
    email = forms.CharField(label='邮箱',
                            validators=[
                                RegexValidator(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', '邮箱格式错误'), ])
    code = forms.CharField(label='验证码', widget=forms.TextInput)

    def clean_code(self):
        email = self.cleaned_data.get('email')
        info_code = self.cleaned_data.get('code')
        # 获取redis的code
        conn = get_redis_connection()
        redis_code = conn.get(email)
        redis_str_code = redis_code.decode('utf-8')
        if str(info_code).strip() != redis_str_code:
            raise ValidationError('验证码错误')
        return info_code


class LoginSms(forms.Form):
    email = forms.CharField(label='邮箱', validators=[
        RegexValidator(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', '邮箱格式错误'),
    ])

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            # 随机验证码
            code = random.randrange(1000, 9999)
            # 发送短信
            sendemail.send_to_one(email, code)
            # 写入redis
            conn = get_redis_connection()
            conn.set(email, code, ex=60)
            return code
        raise ValidationError('该邮箱未注册')


class LoginPwdForm(BootStrapForm, forms.Form):
    username = forms.CharField(label='邮箱或手机号', min_length=2)
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    img_code = forms.CharField(label='图片验证码', widget=forms.TextInput)

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    # 定义钩子方法校验数据
    def clean_img_code(self):
        # 获取用户输入
        code_info = self.cleaned_data.get('img_code')
        # 获取session中的验证码
        img_code = self.request.session.get('img_code')
        if not img_code:
            self.add_error('img_code', '验证码已过期，请重写获取')
        if str(code_info).upper() != str(img_code).upper():
            raise ValidationError('验证码错误')
        return img_code

    def clean_password(self):
        password = self.cleaned_data.get('password')
        return md5(password)
